Thread ক্লাস এবং Runnable ইন্টারফেস দুটি Java-তে multithreading এবং concurrent programming করতে ব্যবহৃত হয়। এই দুটি Java এর java.lang প্যাকেজের অংশ এবং মাল্টিথ্রেডিং অ্যাপ্লিকেশন তৈরি করার জন্য গুরুত্বপূর্ণ ভূমিকা পালন করে।
1. Thread Class
Thread ক্লাস একটি পূর্ণাঙ্গ ক্লাস যা থ্রেড পরিচালনার জন্য প্রয়োজনীয় বিভিন্ন মেথড সরবরাহ করে। এটি java.lang প্যাকেজের একটি ক্লাস এবং java.lang.Runnable ইন্টারফেস ইমপ্লিমেন্ট করে। Thread ক্লাসের মাধ্যমে আপনি একটি নতুন থ্রেড তৈরি করতে পারেন এবং সে থ্রেডে কিছু কার্যক্রম পরিচালনা করতে পারেন।
Thread Class এর মেথড:
start(): এটি থ্রেডকে চালু করে। এটি থ্রেডেরrun()মেথডকে কল করে।run(): এটি থ্রেডের কার্যকলাপ বা কাজ সংজ্ঞায়িত করে। এটিThreadক্লাসে একটি ডিফল্ট মেথড, তবে এটি সাবক্লাসে ওভাররাইড করা যায়।sleep(long millis): থ্রেডের কার্যকলাপ একটি নির্দিষ্ট সময়ের জন্য বন্ধ করে দেয়। এটিInterruptedExceptionছুঁড়ে ফেলে যদি থ্রেডটি বাধাগ্রস্ত হয়।join(): এটি বর্তমান থ্রেডের execution শেষ হওয়ার জন্য অপেক্ষা করে, যখন অন্য কোন থ্রেডে execution চলছে।setPriority(int priority): থ্রেডের প্রাধান্য নির্ধারণ করে।
উদাহরণ (Thread Class):
class MyThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getId() + " Value " + i);
}
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start(); // Starts the first thread
t2.start(); // Starts the second thread
}
}
এখানে, MyThread ক্লাসটি Thread ক্লাসের একটি সাবক্লাস, যা run() মেথডে থ্রেডের কার্যকলাপ সংজ্ঞায়িত করে। start() মেথড কল করলে এই থ্রেড দুটি পৃথকভাবে চলবে।
2. Runnable Interface
Runnable একটি functional interface (Java 8 এর পর থেকে) যা run() মেথড সরবরাহ করে। এটি থ্রেড চালানোর জন্য ব্যবহার করা হয়। Runnable ইন্টারফেসটি thread-safe এবং একাধিক থ্রেডের মধ্যে শেয়ার করা যায়, অর্থাৎ, একটি Runnable ইন্টারফেসের মাধ্যমে একাধিক থ্রেড চালানো সম্ভব।
Runnable Interface এর মেথড:
run(): এটি একটি abstract method যা থ্রেডের কার্যকলাপ সংজ্ঞায়িত করে। আপনি একটি ক্লাসেRunnableইন্টারফেস ইমপ্লিমেন্ট করে এই মেথডটি ওভাররাইড করতে পারেন।
উদাহরণ (Runnable Interface):
class MyRunnable implements Runnable {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getId() + " Value " + i);
}
}
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable); // Passing the Runnable object to the Thread
Thread t2 = new Thread(runnable); // Reusing the same Runnable object
t1.start(); // Starts the first thread
t2.start(); // Starts the second thread
}
}
এখানে, MyRunnable ক্লাসটি Runnable ইন্টারফেস ইমপ্লিমেন্ট করে, যার run() মেথড থ্রেডের কার্যকলাপ সংজ্ঞায়িত করে। দুটি থ্রেড চালানোর জন্য, আমরা Runnable অবজেক্টকে Thread কনস্ট্রাক্টরে পাস করি এবং তারপর start() মেথড কল করি।
3. Thread এবং Runnable এর মধ্যে পার্থক্য:
| বৈশিষ্ট্য | Thread | Runnable |
|---|---|---|
| Inheritance | Thread একটি ক্লাস, যা Thread অবজেক্ট তৈরি করতে ব্যবহৃত হয়। | Runnable একটি ইন্টারফেস, যা run() মেথড সাপোর্ট করে। |
| Extends vs Implements | Thread ক্লাসকে extends করতে হয়। | Runnable ইন্টারফেসকে implements করতে হয়। |
| Multiple Threads | একাধিক থ্রেডের জন্য ব্যবহার করা কঠিন, কারণ একটি ক্লাস শুধুমাত্র একবার extends করা যেতে পারে। | একাধিক থ্রেডের জন্য একই Runnable ইন্টারফেস ব্যবহার করা সম্ভব। |
| Flexibility | কমফোর্টেবল, কিন্তু inheritance সীমাবদ্ধতা থাকে। | বেশি নমনীয় এবং পুনরায় ব্যবহারযোগ্য। |
| Performance | Thread ব্যবহার করে কিছু ক্ষেত্রে একটু কম কার্যক্ষম হতে পারে, কারণ এটি inheritance ব্যবহার করে। | Runnable ব্যবহার করে, বিশেষ করে একাধিক থ্রেডের জন্য, performance বেশি ভালো হতে পারে। |
| Usage | সাধারণত একক থ্রেড তৈরি করার জন্য। | একাধিক থ্রেডের মধ্যে কাজ ভাগ করে নেওয়ার জন্য। |
4. কখন কোনটি ব্যবহার করবেন?
- যদি আপনি single-threaded বা simple multithreaded অ্যাপ্লিকেশন তৈরি করেন, তবে
Threadক্লাস ব্যবহার করা যেতে পারে, তবে আপনার কোডে inheritance এর প্রয়োজন রয়েছে। - যদি আপনার অ্যাপ্লিকেশনটি multiple threads একসাথে চালাবে এবং একই কোড ব্লক বা কার্যকলাপের জন্য একাধিক থ্রেড তৈরি করতে চান, তবে
Runnableইন্টারফেস ব্যবহার করা উচিত।Runnableদিয়ে আপনি একই অবজেক্ট থেকে একাধিক থ্রেড তৈরি করতে পারেন এবং কোডের পুনঃব্যবহারযোগ্যতা বৃদ্ধি পায়। - Thread Class এবং Runnable Interface উভয়ই Java-তে মাল্টিথ্রেডিং অ্যাপ্লিকেশন তৈরি করতে ব্যবহৃত হয়। তবে, Thread ক্লাসকে কেবল একটি থ্রেড চালানোর জন্য ব্যবহার করা হয়, যেখানে Runnable ইন্টারফেসটি অনেকগুলো থ্রেডের মধ্যে ভাগ করা যায় এবং এটি আরো নমনীয়। Runnable ক্লাসটি
Threadএর তুলনায় বেশি পছন্দনীয়, বিশেষত যখন একাধিক থ্রেড একত্রে একই কাজ করবে।
Thread এর ধারণা:
Thread হল একটি একক কার্যকরী একক (execution unit) যা একটি প্রোগ্রামের একটি অংশ হিসাবে কাজ করে। এটি একটি প্রোগ্রামে বিভিন্ন কাজ বা কাজের অংশগুলি সমান্তরালভাবে (concurrently) সম্পাদন করতে সাহায্য করে। Java-তে, Thread একটি বিশেষ ক্লাস যা একটি একক কর্ম (task) চালানোর জন্য ব্যবহৃত হয়। এটি মূলত মাল্টিথ্রেডিং (multithreading) পরিচালনা করতে ব্যবহৃত হয়।
Thread এর মৌলিক বৈশিষ্ট্য:
- Lightweight Process:
- থ্রেড একটি প্রোগ্রামের ভেতরের lightweight প্রসেস হিসেবে কাজ করে। এটি কম মেমরি ব্যবহার করে, কারণ এটি একেই প্রোগ্রামের মধ্যে অন্যান্য থ্রেডগুলির সাথে একত্রে রান করে।
- Concurrency:
- একাধিক থ্রেডের মাধ্যমে একসাথে একাধিক কাজ করা সম্ভব হয়। একটি থ্রেড একটি কাজ করতে থাকলে অন্য থ্রেড অন্য কাজ করে, এবং এই প্রক্রিয়াকে concurrency বলা হয়।
- Independence:
- এক একটি থ্রেড একে অপর থেকে স্বাধীনভাবে কাজ করতে পারে, এবং একাধিক থ্রেড একে অপরের কাজের সাথে সমান্তরালভাবে চলতে পারে।
- Multitasking:
- থ্রেড বিভিন্ন কাজ একসাথে করতে সহায়তা করে, যা multitasking এর অংশ। একাধিক কাজ একই সময়ে চালানো সম্ভব হয়, যেমন একটি থ্রেড একটি কাজ সম্পন্ন করছে এবং অন্য থ্রেড অন্য কাজ।
Thread তৈরি করার উপায়:
Java-তে Thread ক্লাসের দুটি প্রধান পদ্ধতি রয়েছে থ্রেড তৈরি এবং চালানোর জন্য:
- Thread Class এক্সটেন্ড করা:
- একটি নতুন ক্লাস তৈরি করা এবং এতে
Threadক্লাস এক্সটেন্ড করা, তারপরrun()মেথড ওভাররাইড করা।
- একটি নতুন ক্লাস তৈরি করা এবং এতে
- Runnable Interface ইমপ্লিমেন্ট করা:
- একটি ক্লাস তৈরি করা যা
Runnableইন্টারফেস ইমপ্লিমেন্ট করে এবং এরrun()মেথডে কার্যকরী কোড লেখা।
- একটি ক্লাস তৈরি করা যা
Thread তৈরি করা (Thread Class এক্সটেন্ড করে):
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running...");
}
public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); // start() method starts the thread
}
}
Thread তৈরি করা (Runnable Interface ইমপ্লিমেন্ট করে):
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running...");
}
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start(); // start() method starts the thread
}
}
Multithreading এর ধারণা:
Multithreading হল একাধিক থ্রেডের মাধ্যমে একযোগে কাজ করার প্রক্রিয়া। এটি concurrency (সমান্তরাল কার্যক্রম) সক্ষম করে, যেখানে একাধিক কাজ বা প্রক্রিয়া একে অপরের সাথে সমান্তরালভাবে (concurrently) চলে। Multithreading এর মাধ্যমে CPU একটি থ্রেডে কাজ করার সময় অন্য থ্রেডের জন্য অপেক্ষা না করে একাধিক কাজ সম্পন্ন করতে পারে।
Multithreading এর প্রয়োজনীয়তা:
- Performance Improvement (পারফরম্যান্স উন্নয়ন):
- যখন একাধিক থ্রেড একই সময় কাজ করে, তখন সমান্তরালভাবে কাজ হওয়ায় প্রোগ্রামের পারফরম্যান্স বৃদ্ধি পায়। বিশেষ করে CPU-intensive কাজগুলির ক্ষেত্রে।
- Efficient Resource Utilization (সম্পদের কার্যকর ব্যবহার):
- CPU কখনো idle থাকে না, কারণ এক থ্রেড কাজ করার সময় অন্য থ্রেড কাজ করে। এতে CPU-এর সম্পদের ব্যবহার বৃদ্ধি পায়।
- Responsiveness (প্রতিক্রিয়া):
- GUI অ্যাপ্লিকেশনগুলিতে multithreading ব্যবহারের মাধ্যমে, একটি থ্রেড ইউজার ইনপুট গ্রহণ করছে এবং অন্য থ্রেড ব্যাকগ্রাউন্ড কাজ করে। এটি অ্যাপ্লিকেশনকে দ্রুত এবং প্রতিক্রিয়াশীল (responsive) করে তোলে।
Multithreading এর প্রক্রিয়া:
- Thread Scheduling:
- মাল্টিথ্রেডিং এর মাধ্যমে একাধিক থ্রেড সমান্তরালভাবে চলতে থাকে। JVM থ্রেড সিডিউলিং করতে পারে, অর্থাৎ কখন কোন থ্রেড চলবে এবং থ্রেডগুলি কিভাবে CPU সয়ংক্রিয়ভাবে ভাগ করবে তা নির্ধারণ করে।
- Thread Synchronization:
- একাধিক থ্রেড যদি একে অপরের সাথে একই রিসোর্স শেয়ার করে, তখন সঠিকভাবে থ্রেডগুলির সমন্বয় করা উচিত, যাতে ডেটার সমন্বয় ঠিক থাকে এবং thread interference বা data inconsistency না হয়। এক্ষেত্রে synchronization ব্যবহার করা হয়।
- synchronized কিওয়ার্ড থ্রেড সিঙ্ক্রোনাইজ করার জন্য ব্যবহৃত হয়।
Thread Synchronization উদাহরণ:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class MultithreadingExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Thread 1
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
// Thread 2
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start(); // Thread 1 starts
t2.start(); // Thread 2 starts
try {
t1.join(); // Wait for Thread 1 to finish
t2.join(); // Wait for Thread 2 to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final Count: " + counter.getCount()); // Output: 2000
}
}
ব্যাখ্যা:
synchronizedকিওয়ার্ড ব্যবহার করার মাধ্যমেincrement()মেথডটি সিঙ্ক্রোনাইজ করা হয়েছে, যাতে একসাথে একাধিক থ্রেড একই রিসোর্স (এখানেcount) অ্যাক্সেস না করে।join()মেথড ব্যবহার করা হয়েছে, যাতে মূল থ্রেড দুটি সাব-থ্রেডের কাজ শেষ হওয়ার পর কেবল ফলাফল প্রদর্শন করে।
Multithreading এর সুবিধা:
- Improved Performance: একাধিক থ্রেড একযোগে কাজ করে কাজের সময় কমিয়ে দেয় এবং পারফরম্যান্স বাড়ায়।
- Better Resource Utilization: CPU-এর সম্পদের সর্বোত্তম ব্যবহার নিশ্চিত করে।
- Increased Responsiveness: ইউজার ইনপুট দ্রুত গ্রহণ করা সম্ভব হয় এবং ব্যাকগ্রাউন্ড কাজও একসাথে চলে।
- Real-time Processing: রিয়েল-টাইম অ্যাপ্লিকেশনে একাধিক কাজ একসাথে চলতে পারে (যেমন, ভিডিও প্রসেসিং, সিগন্যাল প্রসেসিং ইত্যাদি)।
Thread হল একক কার্যকরী একক (execution unit), যা Java প্রোগ্রামগুলিতে একসাথে একাধিক কাজ সম্পাদন করতে সহায়তা করে। Multithreading হল একাধিক থ্রেড ব্যবহার করে একাধিক কাজ সমান্তরালভাবে সম্পাদন করার প্রক্রিয়া। Java-তে Thread ক্লাস এবং Runnable ইন্টারফেস ব্যবহার করে মাল্টিথ্রেডিং বাস্তবায়ন করা হয়। মাল্টিথ্রেডিং ব্যবহারে performance, resource utilization, এবং responsiveness বৃদ্ধি পায়, তবে সঠিকভাবে থ্রেড সিঙ্ক্রোনাইজেশন এবং সঠিক স্ট্রাকচার ব্যবহারের গুরুত্ব রয়েছে।
Java তে multithreading বা একাধিক থ্রেড ব্যবহারের মাধ্যমে একাধিক কাজ একসাথে সম্পন্ন করা যায়। Thread ক্লাস এবং Runnable ইন্টারফেস দুটি মূল উপাদান যা থ্রেড তৈরি এবং পরিচালনার জন্য ব্যবহৃত হয়। এই দুটি ক্লাস/ইন্টারফেস Java-এ মাল্টিথ্রেডিং সিস্টেম তৈরি করতে গুরুত্বপূর্ণ ভূমিকা পালন করে।
1. Thread ক্লাস
Thread ক্লাস Java তে মাল্টিথ্রেডিং পরিচালনা করার জন্য একটি প্রধান ক্লাস। এই ক্লাসের মাধ্যমে আপনি থ্রেড তৈরি এবং চালনা করতে পারেন। Thread ক্লাস সরাসরি java.lang প্যাকেজে অন্তর্ভুক্ত রয়েছে এবং এটি থ্রেডের সাথে সম্পর্কিত অনেক মেথড সরবরাহ করে।
Thread ক্লাসের ভূমিকা:
- Thread creation:
Threadক্লাস ব্যবহার করে আপনি থ্রেড তৈরি করতে পারেন এবং সেই থ্রেডের কার্যকারিতা পরিচালনা করতে পারেন। - Thread execution:
Threadক্লাসrun()মেথড ব্যবহার করে থ্রেডের কাজ নির্ধারণ করতে সাহায্য করে। - Thread states management:
Threadক্লাস থ্রেডের স্টেট ম্যানেজমেন্ট (যেমন,start(),sleep(),join(),interrupt()) পরিচালনা করতে সাহায্য করে।
Thread ক্লাসের উদাহরণ:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread(); // Create a new thread
thread.start(); // Start the thread
}
}
- এখানে,
MyThreadক্লাসThreadক্লাস থেকে ইনহেরিটেড এবংrun()মেথড ওভাররাইড করা হয়েছে। start()মেথড কল করার মাধ্যমে থ্রেডটি শুরু হয় এবংrun()মেথডটি কল হয়।
2. Runnable ইন্টারফেস
Runnable ইন্টারফেস Java তে মাল্টিথ্রেডিং করার জন্য একটি ফাংশনাল ইন্টারফেস। এটি সাধারণত ব্যবহার করা হয় যখন আপনি থ্রেড তৈরি করতে চান তবে Thread ক্লাসের বাইরেও কাজ করতে চান। আপনি একটি ক্লাসে Runnable ইন্টারফেস ইমপ্লিমেন্ট করে এবং তারপরে থ্রেড চালু করতে পারেন।
Runnable ইন্টারফেসের ভূমিকা:
- Thread execution:
Runnableইন্টারফেসেরrun()মেথডটি থ্রেডের কাজ নির্ধারণ করে। - Thread creation: এটি
Threadক্লাসের মধ্যেRunnableঅবজেক্টকে পাস করে থ্রেড তৈরি করার সুযোগ দেয়। - Flexibility:
Runnableইন্টারফেস ব্যবহার করলে একটি ক্লাস একাধিক ক্লাসের সাথে ইনহেরিট করতে পারে, যাThreadক্লাসের ক্ষেত্রে সম্ভব নয় (কেননাThreadক্লাস নিজেই একটি ক্লাস এবং একাধিক ক্লাস ইনহেরিট করা সম্ভব নয়)।
Runnable ইন্টারফেসের উদাহরণ:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable is running");
}
}
public class RunnableExample {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable(); // Create a new Runnable object
Thread thread = new Thread(myRunnable); // Create a new Thread and pass Runnable object
thread.start(); // Start the thread
}
}
- এখানে,
MyRunnableক্লাসRunnableইন্টারফেস ইমপ্লিমেন্ট করে এবংrun()মেথডের মধ্যে থ্রেডের কাজ প্রদান করা হয়েছে। Threadক্লাসের কন্সট্রাক্টরকেRunnableঅবজেক্ট পাস করে থ্রেড তৈরি করা হয় এবং তারপরstart()মেথড কল করা হয়।
Thread এবং Runnable এর মধ্যে পার্থক্য:
| বৈশিষ্ট্য | Thread ক্লাস | Runnable ইন্টারফেস |
|---|---|---|
| Inheritance | Thread ক্লাস একটি কনক্রিট ক্লাস, সুতরাং এটি শুধুমাত্র একটি ক্লাস থেকেই ইনহেরিট করা যেতে পারে। | Runnable একটি ইন্টারফেস, যেটি একাধিক ক্লাসে ইমপ্লিমেন্ট করা যেতে পারে। |
| Thread Creation | Thread ক্লাস ইনস্ট্যান্স তৈরি এবং run() মেথড ওভাররাইড করে থ্রেড তৈরি করা যায়। | Runnable ইন্টারফেস ইমপ্লিমেন্ট করে run() মেথড তৈরি করতে হয় এবং Thread অবজেক্টে পাস করে থ্রেড তৈরি করা যায়। |
| Flexibility | থ্রেড তৈরি করতে Thread ক্লাসের বাইরের কোনো ক্লাসের সাথে একসাথে কাজ করা যায় না। | একাধিক ইন্টারফেস বা সুপারক্লাস থেকে ইনহেরিট করা যেতে পারে, তাই এটি বেশি নমনীয়। |
| Performance | Thread ক্লাসটি একটু কম নমনীয়, কারণ এটি একটি ক্লাস এবং একাধিক ক্লাস ইনহেরিট করা সম্ভব নয়। | Runnable বেশি পারফরম্যান্সফুল, কারণ এটি একাধিক ক্লাস ইনহেরিট বা ইমপ্লিমেন্ট করা যেতে পারে। |
| Thread Control | Thread ক্লাসে থ্রেড নিয়ন্ত্রণের জন্য কিছু built-in মেথড থাকে, যেমন sleep(), join(), interrupt()। | Runnable ইন্টারফেসে শুধুমাত্র run() মেথড থাকে; থ্রেড নিয়ন্ত্রণের জন্য Thread ক্লাসের মেথড ব্যবহার করতে হয়। |
Thread এবং Runnable ব্যবহার করা:
- Thread Class ব্যবহৃত হয় যখন আপনি সরাসরি থ্রেড তৈরি এবং পরিচালনা করতে চান।
- Runnable Interface ব্যবহৃত হয় যখন আপনি থ্রেড কাজের জন্য কোডটি পুনঃব্যবহারযোগ্য এবং বেশি নমনীয় রাখতে চান, এবং যখন আপনি একাধিক ক্লাস থেকে থ্রেডের কার্যকলাপ করতে চান।
Thread Class ব্যবহার:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread is running");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
Runnable Interface ব্যবহার:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable is running");
}
}
public class RunnableExample {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
- Thread ক্লাস এবং Runnable ইন্টারফেস উভয়ই থ্রেড তৈরি এবং পরিচালনা করতে ব্যবহৃত হয়, তবে তাদের মধ্যে কিছু মৌলিক পার্থক্য রয়েছে।
- Thread ক্লাস এককভাবে একটি থ্রেড তৈরি করতে ব্যবহার করা হয়, তবে Runnable ইন্টারফেস আরও নমনীয় এবং একাধিক ক্লাসের সাথে ব্যবহার করা যায়। Runnable ইন্টারফেস ব্যবহার করে আপনি একাধিক ফিচার ইমপ্লিমেন্ট করতে পারেন, এবং এটি performance দিক থেকেও কিছুটা বেশি সুবিধাজনক।
Thread Lifecycle হল একটি থ্রেডের বিভিন্ন অবস্থার (state) সিরিজ যা একটি থ্রেড তার সৃষ্টি থেকে শুরু করে তার কার্যক্রম শেষ হওয়া পর্যন্ত পাড়ি দেয়। Java তে থ্রেডের lifecycle বেশ কয়েকটি ধাপে বিভক্ত এবং থ্রেডের বিভিন্ন অবস্থার মধ্যে পরিবর্তিত হতে পারে। প্রতিটি ধাপের মধ্যে নির্দিষ্ট কাজ এবং অবস্থান থাকে, যা থ্রেডের কার্যক্ষমতা এবং কন্ট্রোলকে নির্ধারণ করে।
Java তে থ্রেডের lifecycle এবং তার বিভিন্ন ধাপের মধ্যে পার্থক্য করার জন্য আমরা Thread ক্লাস এবং Thread States ধারণা ব্যবহার করি।
Thread Lifecycle
একটি থ্রেড তার জীবনচক্রের মধ্যে ছয়টি ভিন্ন ধাপে থাকতে পারে:
- New (Newborn State)
- Runnable (Ready to Run)
- Blocked
- Waiting
- Timed Waiting
- Terminated (Dead)
1. New (Newborn State)
- একটি থ্রেড যখন তৈরি করা হয়, কিন্তু চালু করা হয়নি, তখন সেটি New অবস্থায় থাকে।
- এই অবস্থায়, থ্রেডটি কেবলমাত্র তৈরি হয়েছে, কিন্তু start() মেথড কল করা হয়নি এবং কাজ শুরু হয়নি।
এটি থ্রেডের প্রথম ধাপ।
Thread t = new Thread();
2. Runnable (Ready to Run)
- থ্রেড যখন start() মেথড কল করা হয়, তখন এটি Runnable অবস্থায় চলে যায়।
- এখানে থ্রেড CPU থেকে কার্যকরী হতে প্রস্তুত থাকে, কিন্তু CPU time slice পাওয়ার জন্য অপেক্ষা করে।
- Runnable অবস্থায় থাকা থ্রেড CPU পাওয়ার জন্য Thread Scheduler এর উপর নির্ভরশীল।
এটি থ্রেডের দ্বিতীয় ধাপ।
t.start(); // Now the thread enters the Runnable state.
3. Blocked
- Blocked অবস্থায় থাকা থ্রেডটি একটি নির্দিষ্ট রিসোর্স (যেমন, I/O অপারেশন বা synchronized ব্লক) অ্যাক্সেস করার জন্য অপেক্ষা করছে।
- এটি তখন ঘটে যখন থ্রেড synchronized ব্লক বা মেথড ব্যবহার করে, এবং ঐ রিসোর্সটি অন্য থ্রেড দ্বারা ব্যস্ত থাকে।
- Blocked অবস্থায় থাকা থ্রেড CPU তে থাকে না, বরং অন্য থ্রেড রিসোর্সটি ব্যবহার করার পর অপেক্ষা করে।
এটি থ্রেডের তৃতীয় ধাপ।
synchronized (someObject) {
// Some code block that will be blocked
}
4. Waiting
- Waiting অবস্থায় থাকা থ্রেডটি অন্য থ্রেডের সিগন্যাল বা নির্দিষ্ট সময়ের জন্য অপেক্ষা করছে।
- এই অবস্থায় থাকলে, থ্রেডটি Object.wait(), Thread.join(), অথবা Thread.sleep() মেথডের মাধ্যমে সময়ক্ষেপণ বা অপেক্ষা করে।
- Waiting অবস্থায় থাকা থ্রেড কেবল অন্য থ্রেডের সিগন্যালের মাধ্যমে পুনরায় Runnable অবস্থায় ফিরে আসতে পারে।
এটি থ্রেডের চতুর্থ ধাপ।
synchronized (someObject) {
someObject.wait(); // The thread enters the Waiting state
}
5. Timed Waiting
- Timed Waiting অবস্থায় থাকা থ্রেডটি একটি নির্দিষ্ট সময়ের জন্য অপেক্ষা করছে, যেমন sleep() বা join() মেথডে সময় নির্দিষ্ট করা হয়।
- এখানে থ্রেডটি একটি নির্দিষ্ট সময়ের জন্য অপেক্ষা করবে, এবং সময় শেষ হলে এটি Runnable অবস্থায় ফিরে আসবে।
এটি থ্রেডের পঞ্চম ধাপ।
Thread.sleep(1000); // The thread enters Timed Waiting state for 1000 milliseconds
6. Terminated (Dead)
- Terminated (Dead) অবস্থায় থাকা থ্রেডটি তার কার্যক্রম সম্পূর্ণ করেছে এবং থ্রেডটি আর পুনরায় চালানো যাবে না।
- এটি তখন ঘটে যখন থ্রেডের run() মেথড সম্পন্ন হয়ে যায় বা থ্রেডটি কোনো কারণে থামিয়ে দেওয়া হয়।
এটি থ্রেডের ষষ্ঠ ধাপ।
t.run(); // After execution, the thread enters the Dead state
Thread Lifecycle Diagram
একটি সাধারণ থ্রেড জীবনচক্রের ডায়াগ্রাম:
+-----------+
| New | ----> Thread is created but not started
+-----------+
|
v
+-----------+
| Runnable | ----> Thread is ready to run, waiting for CPU time
+-----------+
|
v
+-----------+
| Blocked | ----> Waiting for a resource to be available
+-----------+
|
v
+-----------+
| Waiting | ----> Waiting for a signal or a condition to be met
+-----------+
|
v
+-----------+
| Timed | ----> Waiting for a specific time period
+-----------+
|
v
+-----------+
| Terminated| ----> Thread has finished its execution
+-----------+
Thread State Transition:
- New to Runnable:
start()মেথড কল করলে থ্রেড Runnable অবস্থায় চলে যায়। - Runnable to Blocked: যদি থ্রেড একটি synchronized রিসোর্স অ্যাক্সেস করতে চায় এবং তা অন্য থ্রেড দ্বারা ব্যস্ত থাকে।
- Runnable to Waiting: যদি থ্রেড wait(), join(), বা sleep() মেথড ব্যবহার করে।
- Waiting to Runnable: অন্য থ্রেড সিগন্যাল দিলে বা নির্দিষ্ট সময় শেষ হলে থ্রেড Runnable অবস্থায় ফিরে আসে।
- Any state to Terminated: থ্রেড কার্যক্রম সম্পন্ন করলে বা থ্রেডটির run() মেথড শেষ হলে থ্রেড Terminated অবস্থায় চলে যায়।
Java তে থ্রেড লাইফ সাইকেল মোট ৬টি ধাপে বিভক্ত এবং প্রতিটি ধাপে থ্রেড বিভিন্ন অবস্থায় থাকে। এটি Runnable, Blocked, Waiting, Timed Waiting, এবং Terminated এই সব অবস্থার মধ্যে চলে। থ্রেড পরিচালনা করতে এবং সঠিক সময় ও উপায়ে তার অবস্থান শনাক্ত করতে Thread Lifecycle বোঝা অত্যন্ত গুরুত্বপূর্ণ।
Java-তে thread synchronization এবং inter-thread communication হলো দুইটি গুরুত্বপূর্ণ ধারণা যা multithreading প্রোগ্রামিংয়ে ব্যবহৃত হয়। এগুলি একাধিক থ্রেডের মধ্যে সঠিক সমন্বয় এবং তথ্যের নিরাপদ আদান-প্রদান নিশ্চিত করার জন্য প্রয়োজনীয়।
1. Thread Synchronization
Thread Synchronization হল একটি প্রক্রিয়া যার মাধ্যমে একাধিক থ্রেডের মধ্যে রেস কন্ডিশন (race condition) এবং ডেটা ইনকনসিস্টেন্সি প্রতিরোধ করা হয়। যখন একাধিক থ্রেড একই রিসোর্সে একসাথে অ্যাক্সেস করে, তখন সঠিকভাবে থ্রেডগুলির কার্যক্রম সিঙ্ক্রোনাইজ করা প্রয়োজন যাতে তারা একে অপরের ডেটার উপর প্রভাব না ফেলে।
Synchronization এর প্রয়োজনীয়তা:
- Race Condition: যখন একাধিক থ্রেড একই রিসোর্স (যেমন ভেরিয়েবল বা অবজেক্ট) একসাথে অ্যাক্সেস করে এবং তাদের কার্যক্রম সঠিকভাবে সমন্বিত না হয়, তখন তা race condition সৃষ্টি করতে পারে।
- Data Consistency: একাধিক থ্রেড একে অপরের সাথে ঠিকভাবে সমন্বয় না করলে, ডেটার অবস্থা অপরিবর্তিত থাকতে পারে না।
Synchronization এর কৌশল:
Java-তে থ্রেড সিঙ্ক্রোনাইজ করতে synchronized কিওয়ার্ড ব্যবহার করা হয়।
1.1. Method Level Synchronization:
- একটি মেথডকে synchronized করার মাধ্যমে, শুধুমাত্র একটি থ্রেড সেই মেথডে এক্সিকিউট করার অনুমতি পায়। অন্যথায়, অন্য কোন থ্রেড মেথডটি এক্সিকিউট করতে পারবে না যতক্ষণ না প্রথম থ্রেডটি সম্পূর্ণভাবে কাজটি শেষ করে।
class Counter {
private int count = 0;
// Synchronized method
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizedExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Thread 1
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
// Thread 2
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final Count: " + counter.getCount());
}
}
ব্যাখ্যা:
increment()মেথডটি synchronized হওয়ায়, একবারে এক থ্রেডই সেটি এক্সিকিউট করতে পারে। এক থ্রেড কাজ শেষ না করা পর্যন্ত অন্য থ্রেড এটি এক্সিকিউট করতে পারবে না।- এইভাবে race condition এড়ানো হয়।
1.2. Block Level Synchronization:
- কখনো কখনো আপনি পুরো মেথডের পরিবর্তে একটি নির্দিষ্ট ব্লককে সিঙ্ক্রোনাইজ করতে চাইবেন, যাতে কিছু অংশের জন্য একাধিক থ্রেড এক্সিকিউট করতে পারে এবং কিছু অংশ শুধুমাত্র এক থ্রেডই এক্সিকিউট করতে পারে।
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public int getCount() {
return count;
}
}
ব্যাখ্যা:
- এখানে
synchronizedব্লক ব্যবহার করা হয়েছে যা শুধুমাত্রcount++কোড ব্লকটিকে সিঙ্ক্রোনাইজ করবে, ফলে অন্যান্য কোড একসাথে এক্সিকিউট করা যাবে।
2. Inter-thread Communication
Inter-thread Communication হল সেই প্রক্রিয়া যার মাধ্যমে একাধিক থ্রেডের মধ্যে যোগাযোগ করা হয় এবং তারা একে অপরের সাথে সমন্বয় করতে পারে। Java-তে, inter-thread communication করার জন্য তিনটি মূল মেথড ব্যবহার করা হয়:
wait()notify()notifyAll()
এই মেথডগুলো মূলত Object ক্লাসের অন্তর্গত এবং এই মেথডগুলো শুধুমাত্র synchronized ব্লকের মধ্যে ব্যবহার করা যেতে পারে।
2.1. wait() মেথড:
- এটি একটি থ্রেডকে wait বা ব্লক করে রাখে যতক্ষণ না অন্য কোনো থ্রেড তাকে notify করে দেয়।
wait()মেথডটি তখনই ব্যবহার করা যেতে পারে যখন থ্রেডের কোনো নির্দিষ্ট অবস্থার পূর্ণতার জন্য অপেক্ষা করতে হয়।
2.2. notify() মেথড:
- এটি একটি থ্রেডকে notify করে যে সে তার কাজ শেষ করতে পারে এবং wait করা থ্রেডটি পুনরায় কাজ শুরু করতে পারে।
2.3. notifyAll() মেথড:
- এটি সমস্ত wait করা থ্রেডকে notify করে।
Inter-thread Communication Example:
এখানে দুটি থ্রেডের মধ্যে wait() এবং notify() ব্যবহারের একটি উদাহরণ দেয়া হল, যেখানে একটি থ্রেড অপেক্ষা করবে এবং অন্য থ্রেড তাকে notify করবে।
class Processor {
private boolean isProcessed = false;
// Method that simulates waiting for a task to be processed
public synchronized void produce() throws InterruptedException {
while (isProcessed) {
wait(); // Wait until the task is consumed
}
System.out.println("Producing item...");
isProcessed = true;
notify(); // Notify the consumer that the task is done
}
// Method that simulates consuming the task
public synchronized void consume() throws InterruptedException {
while (!isProcessed) {
wait(); // Wait until the task is produced
}
System.out.println("Consuming item...");
isProcessed = false;
notify(); // Notify the producer that the task is done
}
}
public class InterThreadCommunicationExample {
public static void main(String[] args) {
Processor processor = new Processor();
// Producer Thread
Thread producer = new Thread(() -> {
try {
while (true) {
processor.produce();
Thread.sleep(1000); // Simulating time taken for producing
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// Consumer Thread
Thread consumer = new Thread(() -> {
try {
while (true) {
processor.consume();
Thread.sleep(1000); // Simulating time taken for consuming
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producer.start();
consumer.start();
}
}
ব্যাখ্যা:
- Producer থ্রেড
produce()মেথডের মধ্যেwait()ব্যবহার করে, যতক্ষণ নাconsume()মেথড থেকেnotify()করা হয়। - Consumer থ্রেড
consume()মেথডেwait()ব্যবহার করে, যতক্ষণ নাproduce()মেথড থেকেnotify()করা হয়। notify()বাnotifyAll()এর মাধ্যমে থ্রেডগুলোর মধ্যে সমন্বয় করা হয়।
নোট:
- Deadlock: সিঙ্ক্রোনাইজেশন এবং inter-thread communication ব্যবহারের সময় deadlock সমস্যা হতে পারে যদি দুইটি থ্রেড একে অপরের জন্য অপেক্ষা করে থাকে। এই পরিস্থিতি এড়াতে সঠিক synchronization এবং locking মেকানিজম ব্যবহার করতে হবে।
- Thread Safety: Synchronization ব্যবহার করা না হলে একাধিক থ্রেড একই রিসোর্সে একসাথে অ্যাক্সেস করতে গিয়ে ডেটার অবস্থা অপরিবর্তিত থাকতে পারে, যা race condition তৈরি করে।
- Thread Synchronization ব্যবহারের মাধ্যমে আপনি একাধিক থ্রেডের মধ্যে সমন্বয় নিশ্চিত করতে পারেন এবং race conditions থেকে মুক্ত থাকতে পারেন।
- Inter-thread Communication-এর মাধ্যমে বিভিন্ন থ্রেডের মধ্যে নিরাপদে তথ্য আদান-প্রদান করা সম্ভব হয়।
wait(),notify(), এবংnotifyAll()মেথডগুলি এই প্রক্রিয়াকে সহজ করে তোলে।
Read more